#define _CRT_SECURE_NO_WARNINGS 1


//			《 main.c 》

#include "mystdio.h"
#include "mymath.h"
#include <stdio.h>
#include <string.h>

int main()
{
    int a = 10;
    int b = 20;

    //int myAdd(int, int);
    printf("%d+%d=%d\n", a, b, myAdd(a, b));

    //myFILE* my_fopen(const char *psth, const char *flag);
    myFILE* fp = my_fopen("./myfile.txt", "w");
    if (fp == NULL) return 1;

    const char* message = "这是我写的：hello world!\n";
    //ssize_t my_fwrite(myFILE *fp, const char *data, int len);
    my_fwrite(fp, message, strlen(message));

    my_fclose(fp);

    return 0;
}

//————————————————————————————————————————————————————————

//          《 mymath.h 》

#pragma onec

int myAdd(int, int);
int mySub(int, int);


//————————————————————————————————————————————————————————

//          《 mystdio.h 》

#pragma once

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define LINE_SIZE 1024
#define FLUSH_NOW  1            //立即刷新
#define FLUSH_LINE 2            //行刷新
#define FLUSH_FULL 4            //全刷新


struct _myFILE
{
    unsigned int flags;     //标记位
    int fileno;             //文件描述符
    //缓冲区
    char cache[LINE_SIZE];  //行缓冲区
    int cap;                //缓冲区总容量
    int pos;                //下次写入的位置
};
typedef struct _myFILE myFILE;  // C 语言用结构体前面要加 struct 

//打开文件
myFILE* my_fopen(const char* path, const char* flag);

//刷新缓冲区(行刷新)
void my_fflush(myFILE* fp);

//写入
ssize_t my_fwrite(myFILE* fp, const char* data, int len); //文件里写,写的数据,写多长

// 关闭文件
void my_fclose(myFILE* fp);



//————————————————————————————————————————————————————————

[a@192 roommate]$ ll
total 40
- rw - rw - r--. 1 a a  511 May  8 10:22 main.c
- rw - rw - r--. 1 a a 2040 May  8 10 : 26 main.o
- rwxrwxr - x. 1 a a 9072 May  8 10 : 26 myexe
- rw - rw - r--. 1 a a   31 May  8 13 : 06 myfile.txt
- rw - rw - r--. 1 a a   56 May  8 10 : 13 mymath.h
- rw - rw - r--. 1 a a 1344 May  8 10 : 13 mymath.o
- rw - rw - r--. 1 a a  857 May  8 10 : 13 mystdio.h
- rw - rw - r--. 1 a a 2792 May  8 10 : 13 mystdio.o
//运行：
[a@192 roommate]$ . / myexe
10 + 20 = 30

[a@192 roommate]$ cat myfile.txt
这是我写的：hello world!
[a@192 roommate]$


//————————————————————————————————————————————————————————



		《 生成动态库 》


·shared   : 表示生成共享库格式
·fPIC     : 产生位置无关码(position independent code)
·库名规则 : libxxx.so

[a@192 roommate]$ gcc -fPIC -c mymath.c		//生成动态库
[a@192 roommate]$ gcc -fPIC -c mystdio.c		//生成动态库


		< 动态库打包 >
 通过 -shared 把所有 .o 打包成一个 -o 的动态库文件  libmyc.so
 gcc -shared *.o -o libmyc.so

[a@192 roommate2]$ tree mylib /
mylib /
├── include
│   ├── mymath.h
│   └── mystdio.h
└── lib
		└── libmyc.a			//静态库
		└── libmyc.so		//动态库



		《 复制文件夹 并改名 》
[a@192 dir]$ cp -r file01 ./file02

		《 删除文件夹 及其内容 》
[a@192 roommate3D]$ rm -rf file 




//————————————————————————————————————————————————————————


————————————————————————————————————————————————————————————————————————————



			《 对比 动、静 态库 》

2. 
Linux 中:
	.so (动态库)
	.a  (静态库)
windows 中:
	.dll(动态库)
	.lib(静态库)    

————————————————————————————————————————————————————————————————————————————


//头文件 是一个手册 ，提供函数的声明，告诉用户怎么用,
// .o 提供实现，我们只需要补上一个mian，调用头文件提供的方法，
//然后和 .o 进行连接，就能形成 可执行



		《 静态库 --> 库 》

        《 生成静态库 》
[root@localhost linux]# ar -rc libmymath.a
add.o sub.o
ar是gnu归档工具(打包工具)，rc表示(replace(替换) and create(新建)) 当存在多个.o 文件要打包时，存在了就替换，不存在就新建
查看静态库中的目录列表
[root@localhost linux]# ar -tv libmymath.a
rw-r--r--0/0
1240 Sep 15 16:53 2017 add.o
rw-r--r--0/0 1240 Sep 15 16:53 2017 sub.o
t:列出静态库中的文件
v:verbose 详细信息
[root@localhost linux]# gcc main.c -L. -lmymath
-L 指定库路径
-l 指定库名
测试目标文件生成后，
静态库删掉，程序照样可以运行。

//————————————————————————————————————————————————————————————————————————————

//		《 安装 》

//把我们自己写的/路径中/ 所有头文件， 拷贝到库里 的头文件/路径/中
// sudo cp mylib/include/*.h   /usr/include/
//把我们自己写的/路径中/ 所有静态库， 拷贝到系统静态库中
// sudo cp mylib/lib/*.a		/lib64/

//动态库安装：
// sudo cp mylib/lib/libmyc.so	/lib64/

//直接使用时：编译，编译不过，
//C / C++的库，gcc / g++默认是认识c / C++库，
//libmyc.a-- > 别人写的(第三方提供)->gcc / g++ 不认识 -> 要使用 -l
//  gcc main.c -llibmyc.a	//直接使用编译不过
// libmyc.a 名字去掉前缀 lib， 去掉后缀 .a ，剩下的才是它的名称
// gcc main.c -l myc			//编译成功！

// 不建议把自己写的东西 直接安装到库文件中 进行使用
//		《 卸载 》
// 直接删除自己 之前添加进去的东西，就是卸载
// sudo rm /usr/include/mymath.h 
// sudo rm /usr/include/mystdio.h
// sudo rm /lib64/libmyc.a

//————————————————————————————————————————————————————————————————————————————


mylib 中创建的两个目录 include， lib	
[a@192 roommate2]$ tree mylib
mylib
├── include				//拷贝我们自己写的头文件
└── lib					//拷贝我们自己写的 .o 包

			《 拷贝 》
[a@192 mylib]$ cp ../*.h include/
[a@192 mylib]$ cp ../*.a lib/

[a@192 roommate2]$ tree mylib /
mylib /
├── include
│   ├── mymath.h
│   └── mystdio.h
└── lib
└── libmyc.a


把生成的静态库 安装到系统中
[a@192 roommate2]$ sudo cp mylib / include/*.h   /usr/include/		// .h  把我们自己写的库 安装到系统中 
[a@192 roommate2]$ sudo cp mylib / lib/*.a       /lib64				// .o  包



-rw - rw - r--1 whb whb 374 Apr 14 11:43 main.c
drwxrwxr - x4 whb whb 4096 Apr 14 11 : 52 mylib	//拷贝过去后，这个就相当于安装包，就可以不要了
[whb@bite - alicloud roommate]$ rm mylib / -rf	//删除安装包，不影响使用。


			《 库文件本质就是，把 .o 打包 》
//[a@192 roommate2]$ ar -rc libmyc.a *.o		// myc 这个是自己的 库名

C / C++的库，gcc / g++默认是认识c / C++库
libmyc.a-- > 别人写的(第三方提供)->gcc / g++ 不认识->使用： -l
//[a@192 roommate2]$ gcc main.c -l myc			//就可以了

- rwxrwxr - x1 whb whb 17096 Apr 14 11:58 a.out
- rw - rw - r--1 whb whb 374 Apr 14 11 : 56 main.c
[whb@bite - alicloud roommate]$ . / a.out
10 + 20 = 30
[a@192 roommate2]$ cat myfile.txt                       //显示文件内容
这是我写的：hello world!


这样可以吧我们写的 .o 安装到系统中，但是极不推荐：
[a@192 roommate2]$ sudo rm / usr / include / mystdio.h	//卸载我们自己写的非官方代码
[a@192 roommate2]$ sudo rm / usr / include / mymath.h		//2个头文件，一个 .o 包
[a@192 roommate2]$ sudo rm /lib64/ libmyc.a 


————————————————————————————————————————————————————————————————————————————

        《 在当前目录下用自己的库 》

	I 表include ,也要在我的路径下找一下头文件 ：指定用户自定义头文件路径
 gcc 也是进程，有自己的路径 + ./mylib/include/ 就找到了我的头文件
[a@192 roommate2]$ gcc main.c -I ./mylib/include/
 链接报错！

 L 也要把我们写的 库 .o 链接上去，                -L + 路径(指定用户自定义 库文件路径)
[a@192 roommate2]$ gcc main.c -I ./mylib/include/ -L ./mylib/lib
报错！
（该目录可能存在很多库,具体要找谁呢？）
(注意：libmyc.a库名要去掉 前缀lib，后缀.a ==> myc ) 
 -l (link：执行确定的第三方库 名称)

在当前目录下用自己的库：
[a@192 roommate2]$ gcc main.c -I ./mylib/include/ -L ./mylib/lib -l myc		


————————————————————————————————————————————————————————————————————————————


			《 头文件的 < > 和 " " 》

 头文件不包含在库中时,去掉 I 
[a@192 roommate2]$ gcc main.c -L ./mylib/lib -l myc	

#include <mylib/include/mymath.h>		// < > 会在系统的目录下去找
 找不到！

在当前目录下 找到
#include "mylib/include/mystdio.h"	// " " 会优先在当前目录下找。
#include "mylib/include/mymath.h"


————————————————————————————————————————————————————————————————————————————


没有强制要求 静态链接 -static 
没有动态库时，静态库也能用, 此时 libmyc.a 静态库被局部的拷贝到 a.out 
所以：ldd a.out 查不到使用了静态库。

静态库形成的可执行文件太大，不方便下载。所以打多情况我们使用 动态库。

a.out  libmyc.a  main.c  myfile.txt  mylib  mylib2  mymath.h  mystdio.h
[a@192 roommate2]$ . / a.out
10 + 20 = 30
[a@192 roommate2]$ ldd a.out		
linux - vdso.so.1 = > (0x00007fffd8f8c000)
libc.so.6 = > / lib64 / libc.so.6 (0x00007fb5debed000)
 lib64 / ld - linux - x86 - 64.so.2 (0x00007fb5defbb000)
[a@192 roommate2]$ tree mylib
mylib
├── include
│   ├── mymath.h
│   └── mystdio.h
└── lib
└── libmyc.a

2 directories, 3 files


————————————————————————————————————————————————————————————————————————————


